#pragma once
#include <d3d9.h>
#include <d3dx9.h>
#include <vector>
#include <string>
#include <map>
#include "md5View.h"
#include "../utility/Gets.h"
#include "../utility/defs.h"
#include "../utility/math.h"
#include "../utility/vertex.h"

//=========Mgr
#include "../shaderMgr.h"
#include "../textureMgr.h"
#include "../modelMgr.h"
#include "../luaMgr.h"
//=========

using namespace std;

/*
================
	cMd5Model
================
*/
const float scalefactor = 1.0f;
typedef void (*fpUpdateModel)( float dt );
typedef void (*fpOnInitModel)();

class cMd5Model
{
public:
	cMd5Model();
	~cMd5Model();
	void OnInit( string modelfile, string keyname );
	void Update(float dt);
	void Render();
	void Release();

	void Animate( string animname );

	void SetWorldMatrix( D3DXMATRIX matWorld );
	void SetModelID( string modelID );
	void SetCurrAnim( string currAnim );
	void SetPos( D3DXVECTOR3 pos );
	void SetDir( D3DXVECTOR3 dir );
	void SetAngle( float angle );

	string GetCurrAnim(){ return m_currAnim; }
	D3DXVECTOR3 GetPos(){ return m_vecPos; }
	D3DXVECTOR3 GetDir(){ return m_vecDir; }
	float GetAngle(){ return m_fAngle; }

	void ConfigWorldMatrix();
	void WrapUpdate( string anim, bool& update, float& elapsedTime );
private:
	void CreateMesh();
	void CreateMaterial();
	void GenerateMeshVert( Mesh* & pMesh, int iMesh, vector<Joint>& skeleton );

	void GenerateFrameSkeleton( int m_iFrame, string key, vector<Joint>& skeleton );
	void InterpolateSkeleton( int currFrame, int nextFrame, string animname );
	
private:
	string m_modelID;
	string m_currAnim;
	int m_iFrame;

	D3DXVECTOR3 m_vecPos;
	D3DXVECTOR3 m_vecDir;
	float m_fAngle;

	D3DXMATRIX m_matWorld;

	LPDIRECT3DDEVICE9 m_pDevice9;
	vector<LPD3DXMESH> vecMesh;

	cTextureMgr* m_pTextureMgr;
	cShaderMgr* m_pShaderMgr;
	cModelMgr* m_pModelMgr;

	Md5Model* m_pMd5Model;

	vector<Joint> vecSkeleton;
	vector<Joint> vecInterpSkeleton;
};


class cModel: public cMd5Model
{
public:
	cModel();
};


/*
====================
ModelBuilder
====================
*/


class cModelBuilder
{
public:
	cModelBuilder();
	void OnInit();
	void Render();
	void Update( float dt );
	void Release();

	vector< cModel* >& GetVecModel(){
		return vecModel;
	}
private:
	bool CreateModel( lua_State* pL, int iModel, cModel* pModel );
	void SetModelAnim( int iModel, string currAnim );
	void SetModelWorldMat( int iModel, D3DXMATRIX mat );
	void LuaUpdate( lua_State* pL );
	
	void SetLuaModelInfo( lua_State* pL );
	void UpdateModel( lua_State* pL );

private:
	vector< cModel* > vecModel;

	cShaderMgr* m_pShaderMgr;
	cLuaMgr* m_pLuaMgr;

	fpUpdateModel fpUpdate;
	fpOnInitModel fpOnInit;
};

